#ifndef _MY_LOG_DEFINED_
#define _MY_LOG_DEFINED_
static const char * const MY_LOG_PROCS[] = {"getevent_finalx","sendevent_finalx"};
#ifndef LOG_TAG
# define LOG_TAG __FILE__
#endif  //LOG_TAG
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>        //gettid()
#include <time.h>
#include <assert.h>
#ifdef __ANDROID__
# include <android/log.h>   //for android build and ndk <system/core/include/>
# define ____LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ##__VA_ARGS__)
# define _MY_ENDL_
#else
# define _GNU_SOURCE
# include <sys/syscall.h>   //gettid
# include <sys/time.h>      //gettimeofday
# define gettid() syscall(__NR_gettid)
# define ____LOGD printf
# define _MY_ENDL_ "\n"
#endif

//anyway
# define ____LOGD printf
# define _MY_ENDL_ "\n"
# undef __ANDROID__

static __attribute__ ((unused)) int __is_proc_self() {
    FILE *f_status = NULL;
    char buffer[128] = {0};
    int ret = 0;

    if (sizeof(MY_LOG_PROCS) == 0) {
        ret = 1;
    } else {
        f_status = fopen("/proc/self/cmdline", "r");
        fread(buffer, 128, 1, f_status);
        int loop = (int) (sizeof(MY_LOG_PROCS) / sizeof(MY_LOG_PROCS[0]) - 1);

        for(; loop >= 0; loop --) {
            //____LOGD("readed: [%s], MY_LOG_PROCS[%i]: [%s]", buffer, loop, MY_LOG_PROCS[loop]);
            if ( strstr(MY_LOG_PROCS[loop], buffer) || strstr(buffer, MY_LOG_PROCS[loop]) ) {
                ret = 1;
                break;
            }
        }
        fclose(f_status);
    }
    return ret;
}

static __attribute__ ((unused)) const char *__get_prefix(const char *_tag_, char *buf, int bufsize) {
#ifdef __ANDROID__
    (void) _tag_;
    (void) buf;
    (void) bufsize;
    return "\0";
#else
    if (NULL == _tag_ || NULL == buf || bufsize == 0) {
        return "\0";
    }
    struct timeval _tv;
    struct tm _tm;
    gettimeofday(&_tv, NULL);
    localtime_r(&_tv.tv_sec, &_tm);
    memset(buf, '\0', bufsize);
    snprintf(buf, bufsize, "%02d-%02d %02d:%02d:%02d.%03d %s: ",
            1+_tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec, (int)_tv.tv_usec/1000, _tag_);
    return buf;
#endif
}

#define _MY_VARTOKEN(x, y) x##y
#define __MY_VARTOKEN(x, y) _MY_VARTOKEN(x, y)
#define __my_log(color, _func_, _line_, ...) do { \
    if (__is_proc_self()) { \
        char formated[512] = {0}; \
        char buf_prefix[128] = {0};\
        snprintf(formated, sizeof(formated), ##__VA_ARGS__); \
        ____LOGD("%s" "\033[" "%s[T%ld %s L%d] %s" "\033[0m" _MY_ENDL_, \
                __get_prefix(LOG_TAG, buf_prefix, sizeof(buf_prefix)), color, (long) gettid(), _func_, _line_, formated); \
    }\
} while (0) //define MY_LOG
#define MY_LOG(...)  __my_log("01;36m", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define MY_LOGE(...) __my_log("01;31m", __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define MY_LOGIF(cond, fmt, ...)  do {if(cond){MY_LOG(fmt, ##__VA_ARGS__); } } while(0)
#define MY_LOGEIF(cond, fmt, ...) do {if(cond){MY_LOGE(fmt, ##__VA_ARGS__);} } while(0)
#define MY_ASSERT(cond) do{/*avoid run twice*/ \
    const void * __MY_VARTOKEN(_cond_, __LINE__) = (const void *) (cond); \
    MY_LOGEIF((!__MY_VARTOKEN(_cond_, __LINE__)), "'" #cond "' Assert Fail!"); \
    assert(__MY_VARTOKEN(_cond_, __LINE__)); \
} while(0)
static int __attribute__ ((unused)) __my_intr(char *path, const char *_func_, int _line_) {
    char strvalue[32] = {'\0'};
    FILE *filePath = fopen(path, "r");
    int ret = -1024;
    if (filePath != NULL) {
        if(fread(strvalue, 1, sizeof(strvalue), filePath) > 0) {
            ret = atoi(strvalue);
            __my_log("01;36m", _func_, _line_, "%s readed %d ", path, ret);
        } else {
            __my_log("01;36m", _func_, _line_, "Fail to read: %s", path);
        }
        fclose(filePath);
    } else {
        __my_log("01;36m", _func_, _line_, "Fail to open: %s", path);
    }
    return ret;
}
#define MY_INTW(path, value) do{ \
    char strvalue[32] = {'\0'}; \
    FILE *filePath = fopen(path, "w"); \
    snprintf(strvalue, 1, "%d", value); \
    if (filePath != NULL) { \
        if(strlen(strvalue) == fwrite(strvalue, 1, strlen(strvalue), filePath)) { \
            MY_LOGE("ERROR write %d to %s", value, path);\
        } else {\
            MY_LOG("written %d to %s", value, path);\
        }\
        fclose(filePath); \
    } else { \
        MY_LOGE("Fail to open: %s", path);\
    }\
} while(0)
#define MY_INTR(path)  __my_intr(path, __FUNCTION__, __LINE__)
#endif //_MY_LOG_DEFINED_
